from http.client import responses

from django.http import HttpResponseBadRequest, JsonResponse, HttpResponse
from django.shortcuts import render
# 提取code请求参数
# 使用code向QQ服务器请求access_token
# 使用access_token向QQ服务器请求openid
# 使用openid查询该QQ用户是否在美多商城中绑定过用户
# 如果openid已绑定美多商城用户，直接生成JWT token，并返回
# 如果openid没绑定美多商城用户，创建用户并绑定到openid
# Create your views here.
from django import http
from django.conf import settings
from django.views import View
from QQLoginTool.QQtool import OAuthQQ
import logging
logger = logging.getLogger('django')

from apps.oauth.models import OAuthQQUser
from django.contrib.auth import login
import json
import re
from apps.users.models import User
# from .utils import check_access_token
from django.db import DatabaseError
from django_redis import get_redis_connection


class QQAuthURLView(View):
    """提供QQ登录页面网址
    https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id=xxx&redirect_uri=xxx&state=xxx
    """
    def get(self, request):
        # next表示从哪个页面进入到的登录页面，将来登录成功后，就自动回到那个页面
        next = request.GET.get('next')
        # 获取QQ登录页面网址
        #.初始化OAuthQQ对象，settings.py
        oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID,
                        client_secret=settings.QQ_CLIENT_SECRET,
                        redirect_uri=settings.QQ_REDIRECT_URI,
                        state=next)
        #.获取QQ登录扫码页面，扫码后得到Authorization Code
        login_url = oauth.get_qq_url()
        return JsonResponse({'code': 0,'errmsg': 'OK','login_url':login_url})
class QQAuthUserView(View):
    """用户扫码登录的回调处理"""
    def get(self, request):
        """Oauth2.0认证"""
        #1. 接收Authorization Code
        code = request.GET.get('code')
        if not code:
            return HttpResponseBadRequest({'code': 400,'errmsg':'参数不全'})
        #2.使用code向QQ服务器请求access_token
        # 创建工具对象
        oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID,
                        client_secret=settings.QQ_CLIENT_SECRET,
                        redirect_uri=settings.QQ_REDIRECT_URI)
        access_token = oauth.get_access_token(code)
        # 使用access_token向QQ服务器请求openid
        openid = oauth.get_open_id(access_token)
        #判断openid是否绑定过用户
        from apps.oauth.models import OAuthQQUser
        try:
             oauth_user = OAuthQQUser.objects.get(openid=openid)
        except OAuthQQUser.DoesNotExist:
            # 如果openid没绑定美多商城用户
            #openid属于用户的隐私信息，所以需要将openid签名处理，避免暴露
            from apps.oauth.utils import generate_access_token
            openid = generate_access_token(openid)
            response=JsonResponse({'code':400,'access_token':openid})
            return response
        else:
            # 如果openid已绑定美多商城用户
            from django.contrib.auth import login
            login(request, oauth_user.user)
            response = JsonResponse({'code':0,'errmsg':'OK'})
            response.set_cookie('openid', oauth_user.openid)
            return response

    # 保存
    def post(self, request):
        """美多商城用户绑定到openid"""
        # 1.接收参数
        data_dict = json.loads(request.body.decode())
        mobile = data_dict.get('mobile')
        password = data_dict.get('password')
        sms_code_client = data_dict.get('sms_code')
        openid = data_dict.get('access_token')
        from apps.oauth.utils import check_access_token
        openid = check_access_token(openid)
        if openid is None:
            return JsonResponse({'code':400,'errmsg':'参数缺失'})
        # 2.校验参数
        # 判断参数是否齐全
        if not all([mobile, password, sms_code_client]):
            return JsonResponse({'code': 400,'errmsg': '缺少必传参数'})
        # 判断手机号是否合法
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return JsonResponse({'code': 400,'errmsg': '请输入正确的手机号码'})
        # 判断密码是否合格
        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            return JsonResponse({'code': 400,'errmsg': '请输入8-20位的密码'})
        # 3.判断短信验证码是否一致
        # 创建 redis 链接对象:
        redis_conn = get_redis_connection('code')
        # 从 redis 中获取 sms_code 值:
        sms_code_server = redis_conn.get('sms_%s' % mobile)
        # 判断获取出来的有没有:
        if sms_code_server is None:
            # 如果没有, 直接返回:
            return http.JsonResponse({'code': 400,'errmsg': '验证码失效'})
        # 如果有, 则进行判断:
        if sms_code_client != sms_code_server.decode():
            # 如果不匹配, 则直接返回:
            return http.JsonResponse({'code': 400,'errmsg': '输入的验证码有误'})
        # 调用我们自定义的函数, 检验传入的 access_token 是否正确:
        # 错误提示放在 sms_code_errmsg 位置
        # openid = check_access_token(access_token)
        # if not openid:
        #     return http.JsonResponse({'code': 400,'errmsg': '缺少openid'})
        # 4.保存注册数据
        try:
            user = User.objects.get(mobile=mobile)
        except User.DoesNotExist:
            # 用户不存在,新建用户
            user = User.objects.create_user(username=mobile,
                                            password=password,
                                            mobile=mobile)
        else:
            # 如果用户存在，检查用户密码
            if not user.check_password(password):
                return JsonResponse({'code': 400,
                                          'errmsg': '输入的密码不正确'})
        # 5.将用户绑定 openid
        try:
            OAuthQQUser.objects.create(openid=openid,
                                       user=user)
        except DatabaseError:
            return JsonResponse({'code': 400,
                                      'errmsg': '往数据库添加数据出错'})
        # 6.实现状态保持
        login(request, user)

        # 7.创建响应对象:
        response =JsonResponse({'code': 0,
                                      'errmsg': 'ok'})
        # 8.登录时用户名写入到 cookie，有效期14天
        response.set_cookie('username',
                            user.username,
                            max_age=3600 * 24 * 14)
        # 合并购物车
        # 需求：用户登录时，将cookie购物车数据合并到Redis购物车数据中。
        from apps.carts.utils import merge_cart_cookie_to_redis
        response = merge_cart_cookie_to_redis(request=request, user=user, response=response)
        # 9.响应
        return response
#openid属于用户的隐私信息，所以需要将openid签名处理，避免暴露
# from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
# from django.conf import settings
# def generate_access_token(openid):
#     """
#     签名openid
#     :param openid: 用户的openid
#     :return: access_token
#     """
#     serializer = Serializer(settings.SECRET_KEY, expires_in=1)
#     data = {'openid': openid}
#     token = serializer.dumps(data)
#     return token.decode()